package config;

import org.dom4j.Node;
import pojo.Context;
import pojo.Host;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import pojo.Wrapper;
import server.HttpServlet;
import server.Servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandler;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ServerConfiguration {


    public List<Host> parseServer() {
        List<Host> hostList = new ArrayList<>();
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("server.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();
            List<Element> serviceElementList = rootElement.selectNodes("//Service");
            if (serviceElementList == null || serviceElementList.size() == 0) {
                return null;
            }
            for (Element service : serviceElementList) {
                Element connectorElement = (Element) service.selectSingleNode("//Connector");
                Element engineElement = (Element) service.selectSingleNode("//Engine");
                if (engineElement == null || connectorElement == null || connectorElement.attributeValue("port") == null) {
                    continue;
                }
                List<Element> hostElementList = engineElement.selectNodes("//Host");
                if (hostElementList == null || hostElementList.size() == 0) {
                    continue;
                }

                List<Context> contextList = new ArrayList<>();
                int port = Integer.parseInt(connectorElement.attributeValue("port"));
                for (Element hostElement : hostElementList) {
                    Context context  = new Context();
                    context.setHost(hostElement.attributeValue("name"));
                    context.setWrapperList(loadServlet(hostElement.attributeValue("appBase")));
                    contextList.add(context);
                }
                Host host = new Host();
                host.setPort(port);
                host.setContextList(contextList);
                hostList.add(host);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return hostList;
    }

    public List<Wrapper> loadServlet(String path) throws IOException {
        List<Wrapper> wrapperList = new ArrayList<>();

        URL[] urls = new URL[1];
        URLStreamHandler streamHandler = null;
        String filePath = (path + "\\WEB-INF\\classes").replace("\\", File.separator);
        File classPath = new File(filePath);
        String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString();
        urls[0] = new URL(null, repository, streamHandler);

        URLClassLoader loader = new URLClassLoader(urls);

        try {
            SAXReader saxReader = new SAXReader();
            Document document = saxReader.read(new FileInputStream((path + "\\WEB-INF\\web.xml").replace("\\", File.separator)));
            Element rootElement = document.getRootElement();

            List<Element> selectNodes = rootElement.selectNodes("//servlet");
            for (int i = 0; i < selectNodes.size(); i++) {
                Element element =  selectNodes.get(i);
                // <Wrapper-name>lagou</Wrapper-name>
                Element servletnameElement = (Element) element.selectSingleNode("servlet-name");
                String servletName = servletnameElement.getStringValue();
                // <Wrapper-class>server.LagouServlet</Wrapper-class>
                Element servletclassElement = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletclassElement.getStringValue();

                // 根据servlet-name的值找到url-pattern
                Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                // /lagou
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();

                Wrapper wrapper = new Wrapper();
                wrapper.setUrlPattern(urlPattern);
                Class<?> aClass = loader.loadClass(servletClass);
                wrapper.setServlet((HttpServlet) aClass.newInstance());
                wrapperList.add(wrapper);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return wrapperList;
    }
}
